import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_hx/model/result.dart';
import '../base/constant.dart';
import 'intercept/header_intercept.dart';
import 'intercept/response_intercept.dart';
export '../model/app_error.dart';
class HttpGo {
  static const int connectTimeout = 1000*60;
  static const int receiveTimeout = 1000*60;
  static final _cancelTokens = <String, CancelToken>{};
  late Dio dio;

  static final HttpGo _singleInstance = HttpGo._internal();
  static HttpGo get instance => HttpGo();

  factory HttpGo() {
    return _singleInstance;
  }

  HttpGo._internal() {
    dio = Dio();
    dio.options.baseUrl = Constant.baseUrl;
    dio.options.connectTimeout = connectTimeout;
    dio.options.receiveTimeout = receiveTimeout;
    //添加请求头
    dio.interceptors.add(HeaderIntercept());
    dio.interceptors.add(ResponseIntercept());

    // setupProxy("PROXY 192.168.3.31:8888");
  }


  void setupProxy(String proxyHostAndPort) async {
    if (proxyHostAndPort.isNotEmpty) {
      (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (client) {
        client.findProxy = (uri) {
          return proxyHostAndPort;
        };
        //忽略证书
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
        return null;
      };
    }
  }



  ///get 请求
  Future<Result<T>> get<T>(String path,{
    Map<String,dynamic>? params,
    bool isAutoLogin=false,
    String? title})async{
    return await doSendRequest(path, method: HttpMethod.get,params: params,title: title);
  }


  ///post请求
  Future<Result<T>> post<T>(String path,{
    Map<String,dynamic>? params,
    Map<String,dynamic>? data,
    Map<String,dynamic>? headers,
    bool isAutoLogin=false,
    String? title})async{
    return await doSendRequest(path,
        method: HttpMethod.post,
        params: params,
        headers:headers,
        data: data,
        title: title);
  }

  ///put请求
  Future<Result<T>> put<T>(String path,{
    Map<String,dynamic>? params,
    Map<String,dynamic>? data,
    String? title})async{
    return await doSendRequest(path,
        method: HttpMethod.put,
        params: params,
        data: data,
        title: title);
  }
  ///delete 请求
  Future<Result<T>> delete<T>(String path,{
    Map<String,dynamic>? params,
    Map<String,dynamic>? data,
    String? title})async{
    return await doSendRequest(path,
        method: HttpMethod.delete,
        params: params,
        data: data,
        title: title);
  }



  Future<Response<dynamic>> _send({required String path, required HttpMethod method,Map<String,dynamic>? headers,Map<String,dynamic>? params,Map<String,dynamic>?data})async{
    switch(method){
      case HttpMethod.get:
        return await dio.get<dynamic>(path,queryParameters: params);
      case HttpMethod.put:
        return await dio.put<dynamic>(path,queryParameters: params,data: data);
      case HttpMethod.delete:
        return await dio.delete<dynamic>(path,queryParameters: params,data: data);
      case HttpMethod.post:
        return await dio.post<dynamic>(path,queryParameters: params,data: data,options: Options(
          headers: headers
        ));
    }
  }



  ///发起请求
  ///@params api
  ///@params isShowLoading 是否显示加载框
  ///@params title 加载的提示语可不传
  ///@params handlers 异常处理器
  Future<Result<T>> doSendRequest<T>(String path,{
    required HttpMethod method,
    Map<String,dynamic>? params,
    Map<String,dynamic>?data,
    Map<String,dynamic>? headers,
    String? title})async{
    return Result.guardFuture(()async{
      final res=await _send(path: path, method: method,params: params,data: data);
      return res.data;
    });
  }

  ///取消请求
  static void cancelHttp(String tag) {
    if (_cancelTokens.containsKey(tag)) {
      var isCancelled=_cancelTokens[tag]?.isCancelled??false;
      if (!isCancelled) {
        _cancelTokens[tag]?.cancel();
      }
      _cancelTokens.remove(tag);
    }
  }
}

enum HttpMethod{
  get,
  post,
  delete,
  put
}